﻿using System;
using System.Collections;
using System.Linq;
using System.Windows.Forms;
using Aurora.DataAccess;
using Aurora.Domain;
using Aurora.Infrastructure;
using ComponentFactory.Krypton.Toolkit;
using Microsoft.Practices.Unity;

namespace Aurora.Core.ViewForms
{
    /// <summary>
    /// Description of MainForm.
    /// </summary>
    public partial class frmMain : KryptonForm
    {
        private IList _dgDataSource;
        private readonly IUnityContainer _container;
        private readonly IRepository _repository;

        public frmMain(IUnityContainer unityContainer)
        {
            InitializeComponent();

            _container = unityContainer;
            _repository = _container.Resolve<IRepository>();
            tabMain_tabChange(this, null);
        }

        /// <summary>
        /// Перезагрузка данных из БД и обновление источников данных для DataGridView на выбранной вкладке.
        /// </summary>
        private void RefreshDataSource()
        {
            try
            {
                switch (tabMainNavi.SelectedIndex)
                {
                    case 0:
                        _dgDataSource =  _repository.GetObjects<ClientCard>() as IList;
                        dgCards.DataSource = _dgDataSource;
                        InitCardsColumns();
                        break;
                    case 1:
                        VisitsAsDataSource();
                        break;
                    case 2:
                        _dgDataSource = _repository.GetObjects<Disease>() as IList;
                        dgDiseases.DataSource = _dgDataSource;
                        InitDiseaseColumns();
                        break;
                    case 3:
                        ServicesAsDataSource();
                        break;
                    case 4:
                        _dgDataSource = _repository.GetObjects<Doctor>() as IList;
                        dgDoctors.DataSource = _dgDataSource;
                        InitDoctorColumns();
                        break;
                    default:
                        return;
                }
            }
            catch (InvalidCastException invalidCastException)
            {
                Messenger.ShowErrorMessage("Invalid cast", invalidCastException.Message);
            }
            catch (ArgumentNullException argumentNullException)
            {
                Messenger.ShowErrorMessage("Invalid parameter", argumentNullException.Message);
            }
        }

        
        /// <summary>
        /// Поиск объекта из выбранной строки, передача его в конструктор editForm и открытие нового экземпляра editForm.
        /// </summary>
        private void EditFormShow()
        {
            if (cmEditDelete.Caller.GetType() != typeof(DataGridViewRow)) return;

            KryptonForm editForm;

            var dgRowSender = (DataGridViewRow)cmEditDelete.Caller;
            var id = (long)dgRowSender.Cells[0].Value;

            switch (tabMainNavi.SelectedIndex)
            {
                case 0:
                    var editableCard = _repository.GetObject<ClientCard>(id);
                    editForm = new frmAddEdit(_repository, editableCard);
                    break;
                case 1:
                    var visitFrm = new frmVisit(_repository, null);
                    visitFrm.ShowForView(id);
                    return;
                case 2:
                    var editableDisease = _repository.GetObject<Disease>(id);
                    editForm = new frmAddEdit(_repository, editableDisease);
                    break;
                case 3:
                    var editableService = _repository.GetObject<Service>(id);
                    editForm = new frmAddEdit(_repository, editableService);
                    break;
                case 4:
                    var editableDoctor = _repository.GetObject<Doctor>(id);
                    editForm = new frmAddEdit(_repository, editableDoctor);
                    break;
                default:
                    return;
            }

            Enabled = false;

            editForm.ShowDialog(this);

            tabMain_tabChange(this, null);
            dgCards.Refresh();

            Enabled = true;
        }

        /// <summary>
        /// Удаление выбранного на DataGridView объекта
        /// </summary>
        private void DeleteObjectOnDataGridView()
        {
            DomainObject domainObject;
            var dgRowSender = (DataGridViewRow)cmEditDelete.Caller;
            var id = (long)dgRowSender.Cells["Id"].Value;

            switch (tabMainNavi.SelectedIndex)
            {
                case 0:
                    domainObject = _repository.GetObject<ClientCard>(id);
                    break;
                case 1:
                    Messenger.ShowExclamation("Записи о приемах не удаляются!");
                    return;
                case 2:
                    domainObject = _repository.GetObject<Disease>(id);
                    break;
                case 3:
                    domainObject = _repository.GetObject<Service>(id);
                    break;
                case 4:
                    domainObject = _repository.GetObject<Doctor>(id);
                    break;
                default:
                    return;
            }

            _repository.Remove(domainObject);
            _repository.SubmitChanges();
        }

        private void ShowChildForm(Form addForm)
        {
            Enabled = false;
            addForm.ShowDialog();
            Enabled = true;
        }
        
        /// <summary>
        /// Обработка и фильтрация вводимых в ТекстБоксы данных
        /// </summary>
        /// <param name="sender">Текстовое поле</param>
        /// <param name="e">Аргументы события</param>
        private void tb_KeyUp(object sender, KeyEventArgs e)
        {
            try
            {
                var textBox = (KryptonTextBox)sender;
                textBox.Text = TextProcessor.RusChar(textBox.Text);
            }
            catch (InvalidCastException)
            {
                Messenger.ShowErrorMessage("Invalid cast exception", "Критическая ошибка. Обратитесь к разработчику.");
            }
            catch (Exception)
            {
                Messenger.ShowErrorMessage("Ошибка применения регулярного выражения",
                                           "Сбой при выполнении программы. Перезапустите приложение или попробуйте повторить ваши действия.");
            }
        }

        private void frmMain_Load(object sender, EventArgs e)
        {
            tabMain_tabChange(this, null);
        }

        private void kryptonContextEdit_Click(object sender, EventArgs e)
        {
            EditFormShow();
        }

        private void dg_CellMouseClick(object sender, DataGridViewCellMouseEventArgs e)
        {
            try
            {
                var dgSender = (KryptonDataGridView)sender;

                dgSender.Rows[e.RowIndex].Selected = true;

                if (e.Button == MouseButtons.Right && e.RowIndex != -1)
                {
                    cmEditDelete.Show(dgSender.Rows[e.RowIndex]);
                }
            }
            catch (InvalidCastException)
            {
                return;
            }
            catch (ArgumentOutOfRangeException)
            {
                ((KryptonDataGridView) sender).Rows[0].Selected = true;
            }
            catch (Exception exception)
            {
                Messenger.ShowErrorMessage("Unexpected error", exception.Message);
            }
        }

        private void mnuDelete_Click(object sender, EventArgs e)
        {
            var dialogResult = Messenger.ShowYesNoQuestion("Вы действительно хотите удалить этот объект?");
            if (dialogResult == DialogResult.No) return;

            DeleteObjectOnDataGridView();
        }

        private void tabMain_tabChange(object sender, EventArgs e)
        {
            RefreshDataSource();
        }

        private void btnAdd_Click(object sender, EventArgs e)
        {
            ShowChildForm(new frmAddEdit(_repository));
        }

        private void btnExit_Click(object sender, EventArgs e)
        {
            Close();
        }

        private void btnVisit_Click(object sender, EventArgs e)
        {
            ShowChildForm(new frmVisit(_repository, null));
            return;
        }

        private void cmEditDelete_Opening(object sender, System.ComponentModel.CancelEventArgs e)
        {
            if(tabMainNavi.SelectedIndex == 0)
            {
                mnuVisits.Visible = true;
            }
            return;
        }

        private void mnuVisits_Click(object sender, EventArgs e)
        {
            ShowCardVisits();
            return;
        }
    }
}